/*
 * seedrand.c
 *
 * Copyright (c) 2002-2003 Bill Jonus
 * Copyright (c) 2004 Tim Jensen
 * Copyright (C) 2011-2012 Dan Reidy <dubkat@ratbox.org>
 * 
 * much ripped from oomon and ported back to C
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 *
 *       Foundation, Inc.
 *       59 Temple Place - Suite 330
 *       Boston, MA  02111-1307, USA.
 *
 *
 *  Project Name: ratbox-monitor
 *    Created on: Dec 4, 2010
 *        Author: Daniel J Reidy <dubkat@ratbox.org>
 *            Id: $Id: seedrand.c 20 2012-03-26 03:55:38Z dubkat $
 *
 *
 */

#include <ratbox_lib.h>
#include <libconfig.h>
#include "setup.h"
#include "common.h"
#include "openmp.h"

int seedscore(const char *);

static const char *allChars =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\\|^_-{[}]`";
static const char *consonants = "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
static const char *leftBrackets = "{[";
static const char *rightBrackets = "}]";
static const char *lower = "abcdefghijklmnopqrstuvwxyz";
static const char *upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char *vowels = "aeiouAEIOU";
static const char *numerics = "0123456789";
static const char *sylableEnd = "bdgjkpqxzBDGJKPQXZ";

static int
isConsonant(char *c)
{
	return (int)strspn(c, consonants);
}

static int
isVowel(char *c)
{
	return (int)strspn(c, vowels);
}

static int
isLeftBracket(char *c)
{
	return (int)strspn(c, leftBrackets);
}

static int
isLower(char *c)
{
	return (int)strspn(c, lower);
}

static int
isNumeric(char *c)
{
	return (int)strspn(c, numerics);
}

static int
isRightBracket(char *c)
{
	return (int)strspn(c, rightBrackets);
}

static int
isSylableEnd(char *c)
{
	return (int)strspn(c, sylableEnd);
}

static int
isUpper(char *c)
{
	return (int)strspn(c, upper);
}



int
seedscore(const char *nick)
{
	struct server *s = &my_server;

	int consonantCount = 0;
	int hyphenCount = 0;
	int leftBracketCount = 0;
	int lowerCount = 0;
	int numericCount = 0;
	int rightBracketCount = 0;
	int upperCount = 0;
	int vowelCount = 0;
	int uniqueCount = 0;

	int score = 0;
	int nicklen;
	int i;

	nicklen = strlen(nick);

	// FNC uses nicks with the first char is a number
	// and nicks less than three chars long is pointless.
	if((s->fnc && isdigit(*(nick))) || nicklen <= 3)
		return 0;


#	pragma omp parallel for \
	reduction(+:score, vowelCount, leftBracketCount, numericCount, rightBracketCount, upperCount, hyphenCount)
	for(i = 0; i < nicklen; i++)
	{
		char *ch = rb_malloc(sizeof(char *));
		char *next = rb_malloc(sizeof(char *));

		sprintf(ch, "%c", nick[i]);

		if(((i + 1) < nicklen))
			sprintf(next, "%c", nick[i + 1]);
		else
			next = NULL;


		if(isConsonant(ch))
		{
			++consonantCount;
			if(next && isConsonant(next) && isSylableEnd(ch) && (ch != next))
			{
				if(isLower(ch) && isUpper(next))
					score += 400;
				else
					score += 800;
			}
		}
		if(isVowel(ch))
			++vowelCount;

		if(isLeftBracket(ch))
			++leftBracketCount;

		if(isNumeric(ch))
			++numericCount;

		if(isRightBracket(ch))
			++rightBracketCount;

		if(isUpper(ch))
			++upperCount;

		if(isLower(ch))
			++lowerCount;

		if(strspn(ch, "-"))
			++hyphenCount;


		if((strspn(ch, "Q") || strspn(ch, "q")) && (strspn(ch, "u") && strspn(ch, "U")))
			score += 400;

		rb_free(ch);
		rb_free(next);

	}

	// XXX dcc bot checks

	// XXX unique count

	if(consonantCount == nicklen)
		score += 1000;

	if((upperCount + numericCount) == nicklen)
		score += 900;

	if(numericCount >= (nicklen - 2))
		score += 750;

	if((hyphenCount > 0) && (numericCount >= 2))
		score += 700;

	if(upperCount > lowerCount)
		score += 600;

	if((numericCount * 2) >= nicklen)
		score += 600;

	if((vowelCount * 3) < consonantCount)
		score += 550;

	if(leftBracketCount != rightBracketCount)
		score += 500;

	return score;
}
